package com.abing.starry.controller;

import com.abing.starry.common.ResultUtils;
import com.abing.starry.model.entity.SystemMonitorEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HWDiskStore;
import oshi.hardware.HardwareAbstractionLayer;
import reactor.core.publisher.Flux;
import reactor.core.scheduler.Schedulers;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.Duration;
import java.util.List;

/**
 * @Author CaptainBing
 * @Date 2024/8/26 16:34
 * @Description
 */
@Slf4j
@RestController
@RequestMapping("/system/monitor")
public class SystemMonitorController {

    @GetMapping
    public SseEmitter systemMonitor() {

        // 建立SSE连接对象 0表示不超时
        SseEmitter sseEmitter = new SseEmitter(0L);

        sseEmitter.onTimeout(() -> {
            log.info("sse timeout");
        });

        sseEmitter.onError((throwable) -> {
            log.error("sse error: {}", throwable.getMessage());
        });

        sseEmitter.onCompletion(() -> {
            log.info("sse complete");
        });

        Flux.interval(Duration.ofSeconds(1))
            .subscribeOn(Schedulers.boundedElastic())
            .doOnNext(i -> {
                try {
                    sseEmitter.send(ResultUtils.success(getSystemMonitorInfo()));
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            })
            .subscribe();

        return sseEmitter;
    }

    private SystemMonitorEntity getSystemMonitorInfo() {

        SystemMonitorEntity systemMonitorEntity = new SystemMonitorEntity();
        SystemInfo systemInfo = new SystemInfo();

        HardwareAbstractionLayer hardware = systemInfo.getHardware();
        GlobalMemory hardwareMemory = hardware.getMemory();

        // 总内存大小，单位：字节
        long systemMemoryTotal = hardwareMemory.getTotal();
        // 可用内存大小，单位：字节
        long systemMemoryAvailable = hardwareMemory.getAvailable();

        // 将内存大小转换为GB并打印
        systemMonitorEntity.setSystemMaxMemory(BigDecimal.valueOf(systemMemoryTotal)
                                                         .divide(BigDecimal.valueOf(1024 * 1024 * 1024L))
                                                         .setScale(2,BigDecimal.ROUND_HALF_UP)
                                                         .floatValue());

        systemMonitorEntity.setSystemUsedMemory(BigDecimal.valueOf(systemMemoryTotal)
                                                          .subtract(BigDecimal.valueOf(systemMemoryAvailable))
                                                          .divide(BigDecimal.valueOf(1024 * 1024 * 1024L))
                                                          .setScale(2,BigDecimal.ROUND_HALF_UP)
                                                          .floatValue());


        CentralProcessor centralProcessor = hardware.getProcessor();
//        System.out.println("Logical Processors: " + centralProcessor.getLogicalProcessorCount()); // 逻辑处理器数量
//        System.out.println("Physical Processor Count: " + centralProcessor.getPhysicalProcessorCount()); // 物理处理器数量

        double systemCpuLoad = centralProcessor.getSystemCpuLoad(1000);
        systemMonitorEntity.setCpuUsage(BigDecimal.valueOf(systemCpuLoad * 100)
                                                  .setScale(2,BigDecimal.ROUND_HALF_UP)
                                                  .floatValue());

        // 磁盘信息
        List<HWDiskStore> diskStores = hardware.getDiskStores();
        // 获取磁盘总大小
        long systemDiskTotal = diskStores.stream().mapToLong(HWDiskStore::getSize).sum();
        systemMonitorEntity.setDiskMax(BigDecimal.valueOf(systemDiskTotal)
                                                 .divide(BigDecimal.valueOf(1024 * 1024 * 1024L))
                                                 .setScale(0,BigDecimal.ROUND_HALF_UP)
                                                 .floatValue());

//        long diskRead = diskStores.stream().mapToLong(HWDiskStore::getReadBytes).sum();
//        monitorMap.put("diskRead",diskRead / 1024 /1024/1024 + "G");
//        long diskWrite = diskStores.stream().mapToLong(HWDiskStore::getReadBytes).sum();
//        monitorMap.put("diskWrite",diskWrite / 1024 /1024/1024 + "G");

        // 系统运行时间
//        long uptimeInSeconds = systemInfo.getOperatingSystem().getSystemUptime();
//        System.out.println("系统运行时间：" + uptimeInSeconds / 3600 + "小时");

        // JVM内存信息
        Runtime runtime = Runtime.getRuntime();
        // jvm最大可分配
        long jvmMaxMemory = runtime.maxMemory();
        // jvm已分配
        long jvmTotalMemory = runtime.totalMemory();
        long jvmFreeMemory = runtime.freeMemory();

        long jvmUsedMemory = jvmMaxMemory - jvmFreeMemory;

        systemMonitorEntity.setJvmMaxMemory(BigDecimal.valueOf(jvmMaxMemory)
                                                      .divide(BigDecimal.valueOf(1024 * 1024 * 1024L))
                                                      .setScale(2,BigDecimal.ROUND_HALF_UP)
                                                      .floatValue());

        systemMonitorEntity.setJvmUsedMemory(BigDecimal.valueOf(jvmUsedMemory)
                                                       .divide(BigDecimal.valueOf(1024 * 1024 * 1024L))
                                                       .setScale(2,BigDecimal.ROUND_HALF_UP)
                                                       .floatValue());

        return systemMonitorEntity;

    }

    public static void main(String[] args) {
        new SystemMonitorController().getSystemMonitorInfo();
    }


}
